package com.flashflexpro.flexdirector.console.agent{
    import com.flashflexpro.flexdirector.conn.ConnWithSocket;

    import com.flashflexpro.flexdirector.conn.RemoteCallingEvent;

    import com.flashflexpro.flexdirector.model.ClassDesc;

    import flash.display.DisplayObject;
    import flash.events.Event;
    import flash.net.Socket;
    import flash.utils.ByteArray;

    public class AgentConnection extends ConnWithSocket{

        public function AgentConnection( socket:Socket, s:DisplayObject ){
            super( socket, s );
            //todo: flash player should ask for crossdomain.xml soon, wait 3 secs, if not kill this;
        }

        //NetManager watching this property, don't change to private var _agent
        [Bindable]
        public var agent:Agent;

        override protected function bytes2Array( ba:ByteArray ):Array{
            var rt:Array;
            try{
                rt = super.bytes2Array( ba );
            }
            catch( e:Error ){
                ba.position = 0;
                var s:String = new String( ba );
                if( s.indexOf( POLICY_FILE_REQUEST ) >= 0 || POLICY_FILE_REQUEST.indexOf( s ) >= 0 ){
                    _socket.writeUTFBytes( DOMAIN_POLICY );
                    _socket.writeUTFBytes( NULL_BYTE );
                    _socket.flush();
                    destroy();
                    throw new Error( CROSS_DOMAIN );
                }
                else{
                    throw e;
                }
            }
            if( rt == null ){
                throw new Error( this + ".bytes2Array no!" )
            }
            return rt;
        }


        private static const DOMAIN_POLICY:String = "<?xml version=\"1.0\"?>\n" + "<cross-domain-policy>\n" +
                "    <allow-access-from domain=\"*\" to-ports=\"*\" />\n" + "</cross-domain-policy>";

        private static const NULL_BYTE:String = '\u0000';
        private static const POLICY_FILE_REQUEST:String = "<policy-file-request/>";


        public function get label():String{
            return _socket.remoteAddress + ":" + _socket.remotePort;
        }

        override public function onPeerCalled( methodName:String, args:Array ):void{
            if( methodName == RemoteCallingEvent.CONNECTED ){
                _connectionId = args[ 0 ];
                _buildInfo = args[ 1 ];
                _instrumented = args[ 2 ];
                CONFIG::debugging{
                    if( _connectionId == null ){
                        trace( this + ".onPeerCalled _appInstId is null!" );
                    }
                    if( _buildInfo == null ){
                        throw new Error( this + ".onPeerCalled _buildInfo is null!" );
                    }
                    if( _instrumented == null ){
                        throw new Error( this + ".onPeerCalled instrumented is null!" );
                    }
                }

                _swfUrl = args[ 3 ];
                _mainSuperClassNames = args[ 4 ];
                CONFIG::debugging{
                    if( _mainSuperClassNames == null ){
                        throw new Error( this + ".onPeerCalled main super class names is null!" );
                    }
                }
                dispatchEvent( new Event( "agentConnected" ) );
            }
            super.onPeerCalled( methodName, args );
        }

        private var _buildInfo:XML;
        [Bindable(event="agentConnected")]
        public function get buildInfo():XML{
            return _buildInfo;
        }

        private var _instrumented:ClassDesc;
        [Bindable(event="agentConnected")]
        public function get instrumented():ClassDesc{
            return _instrumented;
        }

        private var _swfUrl:String;
        [Bindable(event="agentConnected")]
        public function get swfUrl():String{
            return _swfUrl;
        }

        private var _mainSuperClassNames:Array;
        [Bindable(event="agentConnected")]
        public function get mainSuperClassNames():Array{
            return _mainSuperClassNames;
        }

        override protected function onSocketClose( event:Event ):void{
            super.onSocketClose( event );
            agent = null;
        }
    }
}